package com.css.zfzx.fxpg.modules.economicloss.compute.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.css.bpm.platform.api.local.PlatformAPI;
import com.css.bpm.platform.org.division.repository.entity.DivisionEntity;
import com.css.bpm.platform.sys.dict.repository.entity.DictItemEntity;
import com.css.bpm.platform.utils.PlatformDateUtils;
import com.css.bpm.platform.utils.PlatformSessionUtils;
import com.css.bpm.platform.utils.UUIDGenerator;
import com.css.zfzx.fxpg.modules.buildings.census.repository.*;
import com.css.zfzx.fxpg.modules.buildings.census.repository.entity.*;
import com.css.zfzx.fxpg.modules.buildings.census.viewobjects.FxHouseQueryParams;
import com.css.zfzx.fxpg.modules.buildings.data.repository.FxBuildingsNativeRepository;
import com.css.zfzx.fxpg.modules.buildings.data.repository.entity.FxBuildingsEntity;
import com.css.zfzx.fxpg.modules.economicloss.compute.service.FxEconomyLossRiskEvaluateService;
import com.css.zfzx.fxpg.modules.economicloss.middle.repository.FxEconomyLossMiddleNativeRepository;
import com.css.zfzx.fxpg.modules.economicloss.middle.repository.FxEconomyLossMiddleRepository;
import com.css.zfzx.fxpg.modules.economicloss.middle.repository.entity.FxEconomyLossMiddleEntity;
import com.css.zfzx.fxpg.modules.economicloss.middle.viewobjects.FxEconomyLossMiddleQueryParams;
import com.css.zfzx.fxpg.modules.economicloss.probability.repository.FxEconomyLossProbabilityComputeNativeRepository;
import com.css.zfzx.fxpg.modules.economicloss.probability.repository.FxEconomyLossProbabilityComputeRepository;
import com.css.zfzx.fxpg.modules.economicloss.probability.repository.entity.FxEconomyLossProbabilityComputeEntity;
import com.css.zfzx.fxpg.modules.economicloss.probability.viewobjects.FxEconomyLossProbabilityComputeQueryParams;
import com.css.zfzx.fxpg.modules.percent.damage.repository.FxDamagePercentNativeRepository;
import com.css.zfzx.fxpg.modules.percent.damage.repository.entity.FxDamagePercentEntity;
import com.css.zfzx.fxpg.modules.percent.damage.viewobjects.FxDamagePercentQueryParams;
import com.css.zfzx.fxpg.modules.percent.economicloss.repository.FxEconomicLossNativeRepository;
import com.css.zfzx.fxpg.modules.percent.economicloss.repository.entity.FxEconomicLossEntity;
import com.css.zfzx.fxpg.modules.percent.economicloss.viewobjects.FxEconomicLossQueryParams;
import com.css.zfzx.fxpg.modules.vulnerability.danger.repository.FxVulnerabilityDangerNativeRepository;
import com.css.zfzx.fxpg.modules.vulnerability.danger.repository.entity.FxVulnerabilityDangerEntity;
import com.css.zfzx.fxpg.modules.vulnerability.danger.viewobjects.FxVulnerabilityDangerQueryParams;
import com.css.zfzx.fxpg.modules.vulnerability.province.repository.FxVulnerabilityProvinceNativeRepository;
import com.css.zfzx.fxpg.modules.vulnerability.province.repository.entity.FxVulnerabilityProvinceEntity;
import com.css.zfzx.fxpg.modules.vulnerability.province.viewobjects.FxVulnerabilityProvinceQueryParams;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.apache.commons.math3.analysis.FunctionUtils.add;

/**
 * @author andy
 * @date 2020-11-11
 */
@Service
public class FxEconomyLossRiskEvaluateServiceImpl implements FxEconomyLossRiskEvaluateService {

    @Autowired
    private FxBuildingsNativeRepository fxBuildingsNativeRepository;

    @Autowired
    private FxVulnerabilityProvinceNativeRepository fxVulnerabilityProvinceNativeRepository;

    @Autowired
    private FxCityHouseNativeRepository fxCityHouseNativeRepository;
    @Autowired
    private FxCityNonHouseNativeRepository fxCityNonHouseNativeRepository;
    @Autowired
    private FxCountryDlHouseNativeRepository fxCountryDlHouseNativeRepository;
    @Autowired
    private FxCountryFzHouseNativeRepository fxCountryFzHouseNativeRepository;
    @Autowired
    private FxCountryJhHouseNativeRepository fxCountryJhHouseNativeRepository;
    @Autowired
    private FxCountryNonHouseNativeRepository fxCountryNonHouseNativeRepository;

    @Autowired
    private FxEconomyLossMiddleNativeRepository fxEconomyLossMiddleNativeRepository;
    @Autowired
    private FxEconomyLossMiddleRepository fxEconomyLossMiddleRepository;

    @Autowired
    private FxEconomyLossProbabilityComputeNativeRepository fxEconomyLossProbabilityComputeNativeRepository;
    @Autowired
    private FxEconomyLossProbabilityComputeRepository fxEconomyLossProbabilityComputeRepository;


    @Override
    public JSONObject computeEconomicLossEstimateValue(FxEconomyLossMiddleQueryParams queryParams, String userId) {
        JSONObject jsonObject = new JSONObject();

        String provinceName = getDivisionNameByCode("province", queryParams.getProvince());
        String cityName = getDivisionNameByCode("city", queryParams.getCity());
        String areaName = getDivisionNameByCode("district", queryParams.getArea());
        String district = provinceName + "-" + cityName + "-" + areaName;

        if (!fxVulnerabilityProvince.containsKey(district)) {
            FxVulnerabilityProvinceQueryParams fxVulnerabilityProvinceQueryParams = new FxVulnerabilityProvinceQueryParams();
            fxVulnerabilityProvinceQueryParams.setProvince(provinceName);
            fxVulnerabilityProvinceQueryParams.setCity(cityName);
            fxVulnerabilityProvinceQueryParams.setArea(areaName);
            fxVulnerabilityProvince = initFxVulnerabilityProvince(fxVulnerabilityProvinceQueryParams, userId);
        }
        if (damagePercent.size() == 0) {
            FxDamagePercentQueryParams fxDamagePercentQueryParams = new FxDamagePercentQueryParams();
            damagePercent = getDamagePercent(fxDamagePercentQueryParams);
        }
        if (!resetUnitPrice.containsKey(district)) {
            FxEconomicLossQueryParams fxEconomicLossQueryParams = new FxEconomicLossQueryParams();
            fxEconomicLossQueryParams.setProvince(provinceName);
            fxEconomicLossQueryParams.setCity(cityName);
            fxEconomicLossQueryParams.setArea(areaName);
            resetUnitPrice = getResetUnitPrice(fxEconomicLossQueryParams);
        }

        FxHouseQueryParams fxHouseQueryParams = new FxHouseQueryParams();
        fxHouseQueryParams.setProvince(queryParams.getProvince());
        fxHouseQueryParams.setCity(queryParams.getCity());
        fxHouseQueryParams.setArea(queryParams.getArea());
        List<FxBuildingsEntity> fxBuildings = getFxAllHouses(fxHouseQueryParams, userId);

        String[] damageDegrees = new String[]{"0", "1", "2", "3", "4"};
        String[] intensities = new String[]{"6", "7", "8", "9", "10"};
        for (int k = 0; k < intensities.length; k++) {
            for (int n = 0; n < damageDegrees.length; n++) {
                updateEconomicLossMiddleResult(fxBuildings, intensities[k], damageDegrees[n]);
            }
        }
        jsonObject.put("data", "success");
        return jsonObject;
    }
    private List<FxBuildingsEntity> getFxAllHouses (FxHouseQueryParams fxHouseQueryParams, String userId) {

        List<FxBuildingsEntity> fxCityHouses = getFxCityHouses(fxHouseQueryParams, userId);
        /*List<FxBuildingsEntity> fxCityNonHouses = getFxCityNonHouses(fxHouseQueryParams, userId);
        List<FxBuildingsEntity> fxCountryDlHouses = getFxCountryDlHouses(fxHouseQueryParams, userId);
        List<FxBuildingsEntity> fxCountryJhHouses = getFxCountryJhHouses(fxHouseQueryParams, userId);
        List<FxBuildingsEntity> fxCountryNonHouses = getFxCountryNonHouses(fxHouseQueryParams, userId);*/

        //int total = fxCityHouses.size() + fxCityNonHouses.size() + fxCountryDlHouses.size() + fxCountryJhHouses.size() + fxCountryNonHouses.size();
        List<FxBuildingsEntity> fxBuildings = new ArrayList<>();
        fxBuildings.addAll(fxCityHouses);
        /*fxBuildings.addAll(fxCityNonHouses);
        fxBuildings.addAll(fxCountryDlHouses);
        fxBuildings.addAll(fxCountryJhHouses);
        fxBuildings.addAll(fxCountryNonHouses);*/

        return fxBuildings;
    }
    private List<FxBuildingsEntity> getFxCityHouses (FxHouseQueryParams fxCityHouseQueryParams, String userId) {
        List<FxBuildingsEntity> fxBuildings = new ArrayList<>();

        String provinceCode = "", cityCode = "", areaCode = "", provinceName = "", cityName = "", areaName = "";
        List<FxCityHouseEntity> fxCityHouseEntities = fxCityHouseNativeRepository.listFxCityHouses(fxCityHouseQueryParams, userId);
        FxCityHouseEntity fxCityHouseEntity = null;
        for (int i = 0; i < fxCityHouseEntities.size(); i++) {
            fxCityHouseEntity = fxCityHouseEntities.get(i);

            String bh = fxCityHouseEntity.getBh();

            provinceCode = fxCityHouseEntity.getProvince();
            cityCode = fxCityHouseEntity.getCity();
            areaCode = fxCityHouseEntity.getDistrict();

            provinceName = getDivisionNameByCode("province", provinceCode);
            cityName = getDivisionNameByCode("city", cityCode);
            areaName = getDivisionNameByCode("district", areaCode);

            String dcmjStr = fxCityHouseEntity.getDcmj();
            Float dcmj = new Float(dcmjStr != null ? dcmjStr : "0.0");//建筑面积
            String czfwjglx = fxCityHouseEntity.getCzfwjglx();//结构类型
            if (czfwjglx == null) continue;

            FxBuildingsEntity fxBuildingsEntity = new FxBuildingsEntity();
            fxBuildingsEntity.setId(bh);
            fxBuildingsEntity.setProvince(provinceName);
            fxBuildingsEntity.setCity(cityName);
            fxBuildingsEntity.setArea(areaName);
            fxBuildingsEntity.setBuildingArea(dcmj);
            fxBuildingsEntity.setStructureType(czfwjglx);

            fxBuildings.add(fxBuildingsEntity);
        }
        return fxBuildings;
    }
    private List<FxBuildingsEntity> getFxCityNonHouses (FxHouseQueryParams fxCityHouseQueryParams, String userId) {
        List<FxBuildingsEntity> fxBuildings = new ArrayList<>();

        String province = "", city = "", area = "";
        List<FxCityNonHouseEntity> fxCityHouseEntities = fxCityNonHouseNativeRepository.listFxCityNonHouses(fxCityHouseQueryParams, userId);
        FxCityNonHouseEntity fxCityNonHouseEntity = null;
        for (int i = 0; i < fxCityHouseEntities.size(); i++) {
            fxCityNonHouseEntity = fxCityHouseEntities.get(i);

            province = fxCityNonHouseEntity.getProvince();
            city = fxCityNonHouseEntity.getCity();
            area = fxCityNonHouseEntity.getDistrict();

            String dcmjStr = fxCityNonHouseEntity.getDcmj();
            Float dcmj = new Float(dcmjStr != null ? dcmjStr : "0.0");//建筑面积
            String czfwjglx = fxCityNonHouseEntity.getCzfwjglx();//结构类型

            FxBuildingsEntity fxBuildingsEntity = new FxBuildingsEntity();
            fxBuildingsEntity.setProvince(province);
            fxBuildingsEntity.setCity(city);
            fxBuildingsEntity.setArea(area);
            fxBuildingsEntity.setBuildingArea(dcmj);
            fxBuildingsEntity.setStructureType(czfwjglx);

            fxBuildings.add(fxBuildingsEntity);
        }
        return fxBuildings;
    }
    private List<FxBuildingsEntity> getFxCountryDlHouses (FxHouseQueryParams fxCityHouseQueryParams, String userId) {
        List<FxBuildingsEntity> fxBuildings = new ArrayList<>();

        String province = "", city = "", area = "";
        List<FxCountryDlHouseEntity> fxCountryDlHouseEntities = fxCountryDlHouseNativeRepository.listFxCountryDlHouses(fxCityHouseQueryParams, userId);
        FxCountryDlHouseEntity fxCountryDlHouseEntity = null;
        for (int i = 0; i < fxCountryDlHouseEntities.size(); i++) {
            fxCountryDlHouseEntity = fxCountryDlHouseEntities.get(i);

            province = fxCountryDlHouseEntity.getProvince();
            city = fxCountryDlHouseEntity.getCity();
            area = fxCountryDlHouseEntity.getDistrict();

            String dcmjStr = fxCountryDlHouseEntity.getDcmj();
            Float dcmj = new Float(dcmjStr != null ? dcmjStr : "0.0");//建筑面积
            String czfwjglx = fxCountryDlHouseEntity.getJglx();//结构类型

            FxBuildingsEntity fxBuildingsEntity = new FxBuildingsEntity();
            fxBuildingsEntity.setProvince(province);
            fxBuildingsEntity.setCity(city);
            fxBuildingsEntity.setArea(area);
            fxBuildingsEntity.setBuildingArea(dcmj);
            fxBuildingsEntity.setStructureType(czfwjglx);

            fxBuildings.add(fxBuildingsEntity);
        }
        return fxBuildings;
    }
    private List<FxBuildingsEntity> getFxCountryFzHouses (FxHouseQueryParams fxCityHouseQueryParams) {
        List<FxBuildingsEntity> fxBuildings = new ArrayList<>();

        /*String province = "", city = "", area = "";
        List<FxCountryFzHouseEntity> fxCountryDlHouseEntities = fxCountryFzHouseNativeRepository.listFxCountryFzHouses(fxCityHouseQueryParams);
        FxCountryFzHouseEntity fxCountryDlHouseEntity = null;
        for (int i = 0; i < fxCountryDlHouseEntities.size(); i++) {
            fxCountryDlHouseEntity = fxCountryDlHouseEntities.get(i);

            province = fxCountryDlHouseEntity.getProvince();
            city = fxCountryDlHouseEntity.getCity();
            area = fxCountryDlHouseEntity.getDistrict();

            Float dcmj = fxCountryDlHouseEntity.getDcmj();//建筑面积
            String czfwjglx = fxCountryDlHouseEntity.getCzfwjglx();//结构类型

            FxBuildingsEntity fxBuildingsEntity = new FxBuildingsEntity();
            fxBuildingsEntity.setProvince(province);
            fxBuildingsEntity.setCity(city);
            fxBuildingsEntity.setArea(area);
            fxBuildingsEntity.setBuildingArea(dcmj);
            fxBuildingsEntity.setStructureType(czfwjglx);

            fxBuildings.add(fxBuildingsEntity);
        }*/
        return fxBuildings;
    }
    private List<FxBuildingsEntity> getFxCountryJhHouses (FxHouseQueryParams fxCityHouseQueryParams, String userId) {
        List<FxBuildingsEntity> fxBuildings = new ArrayList<>();

        String province = "", city = "", area = "";
        List<FxCountryJhHouseEntity> fxCountryJhHouseEntities = fxCountryJhHouseNativeRepository.listFxCountryJhHouses(fxCityHouseQueryParams, userId);
        FxCountryJhHouseEntity fxCountryJhHouseEntity = null;
        for (int i = 0; i < fxCountryJhHouseEntities.size(); i++) {
            fxCountryJhHouseEntity = fxCountryJhHouseEntities.get(i);

            province = fxCountryJhHouseEntity.getProvince();
            city = fxCountryJhHouseEntity.getCity();
            area = fxCountryJhHouseEntity.getDistrict();

            String dcmjStr = fxCountryJhHouseEntity.getDcmj();
            Float dcmj = new Float(dcmjStr != null ? dcmjStr : "0.0");//建筑面积
            String czfwjglx = fxCountryJhHouseEntity.getJglx();//结构类型

            FxBuildingsEntity fxBuildingsEntity = new FxBuildingsEntity();
            fxBuildingsEntity.setProvince(province);
            fxBuildingsEntity.setCity(city);
            fxBuildingsEntity.setArea(area);
            fxBuildingsEntity.setBuildingArea(dcmj);
            fxBuildingsEntity.setStructureType(czfwjglx);

            fxBuildings.add(fxBuildingsEntity);
        }
        return fxBuildings;
    }
    private List<FxBuildingsEntity> getFxCountryNonHouses (FxHouseQueryParams fxCityHouseQueryParams, String userId) {
        List<FxBuildingsEntity> fxBuildings = new ArrayList<>();

        String province = "", city = "", area = "";
        List<FxCountryNonHouseEntity> fxCountryNonHouseEntities = fxCountryNonHouseNativeRepository.listFxCountryNonHouses(fxCityHouseQueryParams, userId);
        FxCountryNonHouseEntity fxCountryNonHouseEntity = null;
        for (int i = 0; i < fxCountryNonHouseEntities.size(); i++) {
            fxCountryNonHouseEntity = fxCountryNonHouseEntities.get(i);

            province = fxCountryNonHouseEntity.getProvince();
            city = fxCountryNonHouseEntity.getCity();
            area = fxCountryNonHouseEntity.getDistrict();

            String dcmjStr = fxCountryNonHouseEntity.getDcmj();
            Float dcmj = new Float(dcmjStr != null ? dcmjStr : "0.0");//建筑面积
            String czfwjglx = fxCountryNonHouseEntity.getJglx();//结构类型

            FxBuildingsEntity fxBuildingsEntity = new FxBuildingsEntity();
            fxBuildingsEntity.setProvince(province);
            fxBuildingsEntity.setCity(city);
            fxBuildingsEntity.setArea(area);
            fxBuildingsEntity.setBuildingArea(dcmj);
            fxBuildingsEntity.setStructureType(czfwjglx);

            fxBuildings.add(fxBuildingsEntity);
        }
        return fxBuildings;
    }
    private void updateEconomicLossMiddleResult(List<FxBuildingsEntity> fxBuildings, String intensity, String damageDegree) {

        String provinceName = "", cityName = "", areaName = "", district = "", structureType = "";
        Map<String, Map<String, Map<String, Float>>> districtToIntensity2damage22loss = getEconomicLossMiddleResultEntityValue(fxBuildings, intensity, damageDegree);

        FxEconomyLossMiddleQueryParams fxEconomyLossMiddleQueryParams = new FxEconomyLossMiddleQueryParams();
        FxEconomyLossMiddleEntity fxEconomyLossMiddleEntity = null;
        String[] districtNames = null;
        for (Map.Entry<String, Map<String, Map<String, Float>>> entryI : districtToIntensity2damage22loss.entrySet()) {
            district = entryI.getKey();
            districtNames = district.split("-");
            provinceName = districtNames[0];
            cityName = districtNames[1];
            areaName = districtNames[2];

            fxEconomyLossMiddleQueryParams.setProvince(provinceName);
            fxEconomyLossMiddleQueryParams.setCity(cityName);
            fxEconomyLossMiddleQueryParams.setArea(areaName);

            Map<String, Map<String, Float>> intensity2damage22loss = entryI.getValue();
            for (Map.Entry<String, Map<String, Float>> entryJ : intensity2damage22loss.entrySet()) {
                String intensityJ = entryJ.getKey();
                Map<String, Float> damage22loss = entryJ.getValue();
                for (Map.Entry<String, Float> entryK : damage22loss.entrySet()) {
                    String damageK = entryK.getKey();
                    Float loss = entryK.getValue();

                    fxEconomyLossMiddleQueryParams.setEarthquakeIntensity(intensityJ);
                    fxEconomyLossMiddleQueryParams.setDamageDegree(damageK);
                    List<FxEconomyLossMiddleEntity> fxMiddleResults = fxEconomyLossMiddleNativeRepository.getFxEconomyLossMiddles(fxEconomyLossMiddleQueryParams);
                    if (fxMiddleResults.size() == 1) {
                        fxEconomyLossMiddleEntity = fxMiddleResults.get(0);
                        fxEconomyLossMiddleEntity.setCalculatedValue(new BigDecimal(loss));
                        fxEconomyLossMiddleEntity.setUpdateUser(PlatformSessionUtils.getUserId());
                        fxEconomyLossMiddleEntity.setUpdateTime(PlatformDateUtils.getCurrentTimestamp());
                    } else if (fxMiddleResults.size() == 0) {
                        fxEconomyLossMiddleEntity = new FxEconomyLossMiddleEntity();
                        String uuid = UUIDGenerator.getUUID();
                        fxEconomyLossMiddleEntity.setId(uuid);
                        fxEconomyLossMiddleEntity.setProvince(provinceName);
                        fxEconomyLossMiddleEntity.setCity(cityName);
                        fxEconomyLossMiddleEntity.setArea(areaName);
                        fxEconomyLossMiddleEntity.setEarthquakeIntensity(intensityJ);
                        fxEconomyLossMiddleEntity.setDamageDegree(damageK);
                        fxEconomyLossMiddleEntity.setCalculatedValue(new BigDecimal(loss));
                        fxEconomyLossMiddleEntity.setCorrectedValue(new BigDecimal(loss));
                        fxEconomyLossMiddleEntity.setIsValid("1");
                        fxEconomyLossMiddleEntity.setCreateUser(PlatformSessionUtils.getUserId());
                        fxEconomyLossMiddleEntity.setCreateTime(PlatformDateUtils.getCurrentTimestamp());
                    } else {
                        System.out.println(provinceName + ", " + cityName + ", " + areaName + ", intensity: " + intensityJ + ", damageDegree: " + damageK + ", EconomyLossMiddle出现冗余数据!");
                    }
                    this.fxEconomyLossMiddleRepository.save(fxEconomyLossMiddleEntity);
                }
            }
        }
    }
    private Map<String, Map<String, Map<String, Float>>> getEconomicLossMiddleResultEntityValue(List<FxBuildingsEntity> fxBuildings, String intensity, String damageDegree) {

        String provinceName = "", cityName = "", areaName = "", district = "", structureType = "";
        Map<String, Map<String, Map<String, Float>>> districtToIntensity2damage22loss = new HashMap<>();
        for (int i = 0; i < fxBuildings.size(); i++) {

            FxBuildingsEntity fxBuildingsEntity = fxBuildings.get(i);

            provinceName = fxBuildingsEntity.getProvince();
            cityName = fxBuildingsEntity.getCity();
            areaName = fxBuildingsEntity.getArea();
            structureType = fxBuildingsEntity.getStructureType();
            Float buildingArea = fxBuildingsEntity.getBuildingArea();

            district = provinceName + "-" + cityName + "-" + areaName;
            Map<String, Map<String, Map<String, Float>>> type2map = fxVulnerabilityProvince.get(district);

            Map<String, Map<String, Float>> damageDegree2map = type2map.get(structureType);
            Map<String, Float> intensity2vulnerability = damageDegree2map.get(damageDegree);
            Float vulnerability = intensity2vulnerability.get(intensity);

            Map<String, Float> damage2percent = damagePercent.get(structureType);
            Float damagePercent = damage2percent.get(damageDegree);
            Map<String, Float> type2value = resetUnitPrice.get(district);
            Float unitPrice = type2value.get(structureType);

            Float loss = buildingArea * vulnerability * damagePercent * unitPrice;

            if (districtToIntensity2damage22loss.containsKey(district)) {
                Map<String, Map<String, Float>> intensity2damage22loss = districtToIntensity2damage22loss.get(district);
                if (intensity2damage22loss.containsKey(intensity)) {
                    Map<String, Float> damage22loss = intensity2damage22loss.get(intensity);
                    if (damage22loss.containsKey(damageDegree)) {
                        damage22loss.put(damageDegree, damage22loss.get(damageDegree) + loss);
                    } else {
                        damage22loss.put(damageDegree, loss);
                    }
                } else {
                    Map<String, Float> damage22loss = new HashMap<>();
                    damage22loss.put(damageDegree, loss);
                    intensity2damage22loss.put(intensity, damage22loss);
                }
            } else {
                Map<String, Float> damage22loss = new HashMap<>();
                damage22loss.put(damageDegree, loss);
                Map<String, Map<String, Float>> intensity2damage22loss = new HashMap<>();
                intensity2damage22loss.put(intensity, damage22loss);
                districtToIntensity2damage22loss.put(district, intensity2damage22loss);
            }
        }
        return districtToIntensity2damage22loss;
    }

    @Override
    public JSONObject districtEconomicLossCertaintyLoss(FxEconomyLossMiddleQueryParams queryParams, String userId) {

        JSONObject jsonObject = new JSONObject();

        return jsonObject;
    }

    @Override
    public JSONObject districtEconomicLossProbabilityLoss(FxEconomyLossMiddleQueryParams queryParams, String userId) {

        JSONObject jsonObject = new JSONObject();

        return jsonObject;
    }

    @Override
    public JSONObject computeEconomicLossProbability(FxEconomyLossProbabilityComputeQueryParams queryParams, String userId) {

        JSONObject jsonObject = new JSONObject();

        String provinceName = getDivisionNameByCode("province", queryParams.getProvince());
        String cityName = getDivisionNameByCode("city", queryParams.getCity());
        String areaName = getDivisionNameByCode("district", queryParams.getArea());
        String district = provinceName + "-" + cityName + "-" + areaName, structureType = "";

        if (!fxVulnerabilityProvince.containsKey(district)) {
            FxVulnerabilityProvinceQueryParams fxVulnerabilityProvinceQueryParams = new FxVulnerabilityProvinceQueryParams();
            fxVulnerabilityProvinceQueryParams.setProvince(queryParams.getProvince());
            fxVulnerabilityProvinceQueryParams.setCity(queryParams.getCity());
            fxVulnerabilityProvinceQueryParams.setArea(queryParams.getArea());
            fxVulnerabilityProvince = initFxVulnerabilityProvince(fxVulnerabilityProvinceQueryParams, userId);
        }
        if (damagePercent.size() == 0) {
            FxDamagePercentQueryParams fxDamagePercentQueryParams = new FxDamagePercentQueryParams();
            damagePercent = getDamagePercent(fxDamagePercentQueryParams);
        }
        if (!resetUnitPrice.containsKey(district)) {
            FxEconomicLossQueryParams fxEconomicLossQueryParams = new FxEconomicLossQueryParams();
            fxEconomicLossQueryParams.setProvince(provinceName);
            fxEconomicLossQueryParams.setCity(cityName);
            fxEconomicLossQueryParams.setArea(areaName);
            resetUnitPrice = getResetUnitPrice(fxEconomicLossQueryParams);
        }
        if (!vulnerabilityDanger.containsKey(district)) {
            FxVulnerabilityDangerQueryParams fxVulnerabilityDangerQueryParams = new FxVulnerabilityDangerQueryParams();
            fxVulnerabilityDangerQueryParams.setProvince(provinceName);
            fxVulnerabilityDangerQueryParams.setCity(cityName);
            fxVulnerabilityDangerQueryParams.setArea(areaName);
            vulnerabilityDanger = getVulnerabilityDanger(fxVulnerabilityDangerQueryParams);
        }
        if (!probabilityVulnerability.containsKey(district)) {
            probabilityVulnerability = getProbabilityVulnerability(district);
        }

        Map<String, Map<String, Map<String, Float>>> districtToType2Damage22Loss = new HashMap<>();

        FxHouseQueryParams fxHouseQueryParams = new FxHouseQueryParams();
        fxHouseQueryParams.setProvince(queryParams.getProvince());
        fxHouseQueryParams.setCity(queryParams.getCity());
        fxHouseQueryParams.setArea(queryParams.getArea());
        List<FxBuildingsEntity> fxBuildings = getFxAllHouses(fxHouseQueryParams, userId);
        FxBuildingsEntity fxBuildingsEntity = null;
        for (int i = 0; i < fxBuildings.size(); i++) {
            fxBuildingsEntity = fxBuildings.get(i);

            provinceName = fxBuildingsEntity.getProvince();
            cityName = fxBuildingsEntity.getCity();
            areaName = fxBuildingsEntity.getArea();
            structureType = fxBuildingsEntity.getStructureType();
            Float buildingArea = fxBuildingsEntity.getBuildingArea();

            district = provinceName + "-" + cityName + "-" + areaName;

            Map<String, Map<String, Float>> type2Damage22Loss = null;
            if (districtToType2Damage22Loss.containsKey(district)) {
                type2Damage22Loss = districtToType2Damage22Loss.get(district);
            } else {
                type2Damage22Loss = new HashMap<>();
            }
            Float vulnerability = 0.0f, dPercent = 0.0f, loss = 0.0f, unitPrice = resetUnitPrice.get(district).get(structureType);
            String damage = "";
            Map<String, Map<String, Float>> type2map = probabilityVulnerability.get(district);
            Map<String, Float> damage2vulnerability = type2map.get(structureType);
            for(Map.Entry<String, Float> entry : damage2vulnerability.entrySet()) {
                damage = entry.getKey();
                vulnerability = entry.getValue();

                dPercent = damagePercent.get(structureType).get(damage) * 0.01f;
                loss = buildingArea * vulnerability * dPercent * unitPrice;

                if (type2Damage22Loss.containsKey(structureType)) {
                    Map<String, Float> damage22Loss = type2Damage22Loss.get(structureType);
                    if (damage22Loss.containsKey(damage)) {
                        damage22Loss.put(damage, damage22Loss.get(damage) + loss);
                    } else {
                        damage22Loss.put(damage, loss);
                    }
                } else {
                    Map<String, Float> damage22Loss = new HashMap<>();
                    damage22Loss.put(damage, loss);
                    type2Damage22Loss.put(structureType, damage22Loss);
                }

            }
            districtToType2Damage22Loss.put(district, type2Damage22Loss);
        }

        updateOrSaveFxEconomyLossProbabilityComputeEntity(districtToType2Damage22Loss);

        Map<String, Map<String, Double>> districtToK0K1 = computeK0K1(districtToType2Damage22Loss);

        jsonObject.put("data", districtToK0K1);

        return jsonObject;
    }
    private void updateOrSaveFxEconomyLossProbabilityComputeEntity(Map<String, Map<String, Map<String, Float>>> districtToType2Damage22Loss) {
        String district = "", province = "", city = "", area = "", structureType = "", damage = "";
        FxEconomyLossProbabilityComputeQueryParams params = new FxEconomyLossProbabilityComputeQueryParams();
        String[] districtNames = null;
        for(Map.Entry<String, Map<String, Map<String, Float>>> entryI : districtToType2Damage22Loss.entrySet()) {

            district = entryI.getKey();
            districtNames = district.split("-");
            province = districtNames[0];
            city = districtNames[1];
            area = districtNames[2];

            params.setProvince(province);
            params.setCity(city);
            params.setArea(area);

            Float loss = 0.0f;
            Map<String, Float> damageToLoss = new HashMap<>();
            Map<String, Map<String, Float>> type2Damage22Loss = entryI.getValue();
            for(Map.Entry<String, Map<String, Float>> entryJ : type2Damage22Loss.entrySet()) {
                structureType = entryJ.getKey();
                Map<String, Float> damage22Loss = entryJ.getValue();

                for(Map.Entry<String, Float> entryK : damage22Loss.entrySet()) {
                    damage = entryK.getKey();
                    loss = entryK.getValue();
                    if (damageToLoss.containsKey(damage)) {
                        damageToLoss.put(damage, damageToLoss.get(damage) + loss);
                    } else {
                        damageToLoss.put(damage, loss);
                    }
                }
            }

            Float expectation = 0.0f;
            List<FxEconomyLossProbabilityComputeEntity> fxEconomyLossProbabilityComputeEntityList = fxEconomyLossProbabilityComputeNativeRepository.listFxEconomyLossProbabilityComputes(params);
            for (int i = 0; i < fxEconomyLossProbabilityComputeEntityList.size(); i++) {
                FxEconomyLossProbabilityComputeEntity fxEconomyLossProbabilityComputeEntity = fxEconomyLossProbabilityComputeEntityList.get(i);
                Double correctedProbability = fxEconomyLossProbabilityComputeEntity.getCorrectedProbability();
                damage = fxEconomyLossProbabilityComputeEntity.getDamageDegree();
                expectation += correctedProbability.floatValue() * damageToLoss.get(damage);
            }

            for(Map.Entry<String, Float> entryJ : damageToLoss.entrySet()) {
                damage = entryJ.getKey();
                loss = entryJ.getValue();

                params.setProvince(province);
                params.setCity(city);
                params.setArea(area);
                params.setDamageDegree(damage);

                FxEconomyLossProbabilityComputeEntity fxEconomyLossProbabilityComputeEntity = null;
                List<FxEconomyLossProbabilityComputeEntity> fxEconomyLossProbabilityComputeEntities = fxEconomyLossProbabilityComputeNativeRepository.listFxEconomyLossProbabilityComputes(params);
                if (fxEconomyLossProbabilityComputeEntities.size() == 1) {
                    fxEconomyLossProbabilityComputeEntity = fxEconomyLossProbabilityComputeEntities.get(0);
                    fxEconomyLossProbabilityComputeEntity.setEconomicLoss(loss.doubleValue());
                    fxEconomyLossProbabilityComputeEntity.setExpectation(expectation.doubleValue());
                    fxEconomyLossProbabilityComputeEntity.setUpdateUser(PlatformSessionUtils.getUserId());
                    fxEconomyLossProbabilityComputeEntity.setUpdateTime(PlatformDateUtils.getCurrentTimestamp());
                } else if (fxEconomyLossProbabilityComputeEntities.size() == 0) {
                    fxEconomyLossProbabilityComputeEntity = new FxEconomyLossProbabilityComputeEntity();
                    String uuid = UUIDGenerator.getUUID();
                    fxEconomyLossProbabilityComputeEntity.setId(uuid);
                    fxEconomyLossProbabilityComputeEntity.setProvince(province);
                    fxEconomyLossProbabilityComputeEntity.setCity(city);
                    fxEconomyLossProbabilityComputeEntity.setArea(area);
                    fxEconomyLossProbabilityComputeEntity.setDamageDegree(damage);
                    fxEconomyLossProbabilityComputeEntity.setEconomicLoss(loss.doubleValue());
                    fxEconomyLossProbabilityComputeEntity.setExpectation(expectation.doubleValue());
                    fxEconomyLossProbabilityComputeEntity.setIsValid("1");
                    fxEconomyLossProbabilityComputeEntity.setCreateUser(PlatformSessionUtils.getUserId());
                    fxEconomyLossProbabilityComputeEntity.setCreateTime(PlatformDateUtils.getCurrentTimestamp());
                } else {
                    System.out.println(province + ", " + city + ", " + area + ", 破坏程度: " + damage + ": 经济损失概率计算在表中有冗余数据!");
                }
                this.fxEconomyLossProbabilityComputeRepository.save(fxEconomyLossProbabilityComputeEntity);
            }
        }
    }
    private Map<String, Map<String, Double>> computeK0K1(Map<String, Map<String, Map<String, Float>>> districtToType2Damage22Loss) {

        //List<Double> constantYS = new ArrayList<Double>(){{add(0.01); add(0.001); add(0.00001); add(0.000001);}};
        double[] constantYS = new double[]{0.01, 0.001, 0.00001, 0.000001};
        //double[] constantLogYS = new double[]{Math.log(0.01), Math.log(0.001), Math.log(0.00001), Math.log(0.000001)};

        Map<String, Map<String, Double>>  districtToK0K1 = new HashMap<>();

        Double loss = 0.0, vulnerability = 0.0;
        String district = "", structType = "", damage = "";
        Map<String, Map<String, Float>>  type2Damage22Loss = null;
        Map<String, Float> damage22Loss = null;
        for(Map.Entry<String, Map<String, Map<String, Float>>> entryI : districtToType2Damage22Loss.entrySet()) {
            district = entryI.getKey();
            type2Damage22Loss = entryI.getValue();

            //存储区县下：每种房屋类型对应的坐标点
            Map<String, Map<String, List<Double>>> structTypeToAxisName2Coordinate = new HashMap<>();

            //1.每类房屋类型都有五个点, 对应五种破坏类型(0~4)
            for(Map.Entry<String, Map<String, Float>> entryJ : type2Damage22Loss.entrySet()) {
                structType = entryJ.getKey();
                damage22Loss = entryJ.getValue();

                List<Double> coordinateX = new ArrayList<>();
                List<Double> coordinateY = new ArrayList<>();

                for(Map.Entry<String, Float> entryK : damage22Loss.entrySet()) {

                    loss = entryK.getValue().doubleValue();
                    loss = (loss == 0 ? 0.00000000000000000001 : loss);
                    loss = Math.log(loss);

                    damage = entryK.getKey();
                    vulnerability = probabilityVulnerability.get(district).get(structType).get(damage).doubleValue();
                    vulnerability = Math.log(vulnerability);

                    coordinateX.add(loss);
                    coordinateY.add(vulnerability);
                }

                Map<String, List<Double>> axisName2coordinate = new HashMap<>();
                axisName2coordinate.put("X", coordinateX);
                axisName2coordinate.put("Y", coordinateY);
                structTypeToAxisName2Coordinate.put(structType, axisName2coordinate);
            }
            //2.求每类房屋的 K0 K1
            Map<String, Double[]> structTypeToK0K1 = new HashMap<>();
            for(Map.Entry<String, Map<String, List<Double>>> entryJ : structTypeToAxisName2Coordinate.entrySet()) {

                structType = entryJ.getKey();
                Map<String, List<Double>> axisName2coordinate = entryJ.getValue();

                List<Double> coordinateX = axisName2coordinate.get("X");//.slice(1);//slice仅用于测试
                List<Double> coordinateY = axisName2coordinate.get("Y");//.slice(1);

                Map<String, Double> fitResult = fitParams(coordinateX, coordinateY);
                Double a = fitResult.get("a"), b = fitResult.get("b");
                Double K0 = Math.pow(Math.E, b), K1 = -a;

                structTypeToK0K1.put(structType, new Double[]{K0, K1});
            }

            //3.根据已知Y坐标constantYS, 根据几组(K0, K1), 求Y对应的X坐标
            List<List<Double>> XSList = new ArrayList<>();
            for(Map.Entry<String, Double[]> entryJ : structTypeToK0K1.entrySet()) {

                Double[] K0K1 = entryJ.getValue();
                Double K0 = K0K1[0], K1 = K0K1[1];

                List<Double> XS = new ArrayList<>();
                for (int i = 0; i < constantYS.length; i++) {
                    double y = Math.log(constantYS[i]), v = (Math.log(K0) - y) / K1;
                    double x = Math.pow(Math.E, v);
                    XS.add(x);
                }
                XSList.add(XS);
            }

            //4.求新的X坐标
            String idx = "";
            Map<String, Double> idxToXSum = new HashMap<>();
            for (int i = 0; i < XSList.size(); i++) {
                List<Double> XS = XSList.get(i);
                for (int j = 0; j < XS.size(); j++) {
                    idx = String.valueOf(j);
                    if (idxToXSum.containsKey(idx)) {
                        idxToXSum.put(idx, idxToXSum.get(idx) + XS.get(j));
                    } else {
                        idxToXSum.put(idx, XS.get(j));
                    }
                }
            }

            //5.求最后的方程
            List<Double> lastXS = new ArrayList<>();
            for(Map.Entry<String, Double> entryJ : idxToXSum.entrySet()) {
                Double lastX = entryJ.getValue();
                lastX = Math.log(lastX);
                lastXS.add(lastX);
            }
            List<Double> lastYS = new ArrayList<>();
            for (int i = 0; i < constantYS.length; i++) {
                double y = Math.log(constantYS[i]);
                lastYS.add(y);
            }
            Map<String, Double> fitResult = fitParams(lastXS, lastYS);
            Double a = fitResult.get("a"), b = fitResult.get("b");
            Double K0 = Math.pow(Math.E, b), K1 = -a;

            Map<String, Double> K0K1 = new HashMap<>();
            K0K1.put("K0", K0);
            K0K1.put("K1", K1);
            districtToK0K1.put(district, K0K1);
        }
        return districtToK0K1;
    }
    private Map<String, Double> fitParams (List<Double> X, List<Double> Y) {
        Map<String, Double> res = new HashMap<>();
        int len = X.size();
        List<Double> x = new ArrayList<>(len), y = new ArrayList<>(len);
        Double sumX = 0.0, sumY = 0.0;
        for (int n = 0; n < len; n++) {
            x.add(n, X.get(n));
            y.add(n, Y.get(n));
            sumX += x.get(n);
            sumY += y.get(n);
        }
        Double meanX = sumX / len, meanY = sumY / len;

        Double xxbar = 0.0, yybar = 0.0, xybar = 0.0;
        for (int i = 0; i < len; i++) {
            xxbar += (x.get(i) - meanX) * (x.get(i) - meanX);
            yybar += (y.get(i) - meanY) * (y.get(i) - meanY);
            xybar += (x.get(i) - meanX) * (y.get(i) - meanY);
        }
        Double beta1 = xybar / xxbar;
        Double beta0 = meanY - beta1 * meanX;

        Double rss = 0.0;
        Double ssr = 0.0;
        for (int i = 0; i < len; i++) {
            Double fit = beta1 * x.get(i) + beta0;
            rss += (fit - y.get(i)) * (fit - y.get(i));
            ssr += (fit - meanY) * (fit - meanY);
            //ssr += (y[i] - meanY) * (y[i] - meanY);
        }
        //var r_2 = 1 - rss / ssr;
        Double R2 = ssr / yybar;
        res.put("r", R2);
        res.put("a", beta1);
        res.put("b", beta0);
        System.out.println("a: " + beta1 + ", b: " + beta0);
        return res;
    }



    @Override
    public List<DictItemEntity> getValidDictItemsByDictCode(String dictCode) {
        List<DictItemEntity> validDictItems = PlatformAPI.getDictAPI().getValidDictItemsByDictCode(dictCode);
        return validDictItems;
    }

    private Map<String, Map<String, Map<String, Map<String, Float>>>> fxVulnerabilityProvince = new HashMap<>();
    private Map<String, Map<String, Map<String, Map<String, Float>>>> initFxVulnerabilityProvince(FxVulnerabilityProvinceQueryParams queryParams, String userId) {
        //{省-市-区县:
        //  {房屋结构类型: { 破坏程度 : {烈度: 易损性} }
        //  }
        Map<String, Map<String, Map<String, Map<String, Float>>>> fxVulnerabilityProvince = new HashMap<>();

        //  {房屋结构类型: {
        //      破坏程度 : {烈度: 易损性}
        //      }
        //  }
        //Map<String, Map<String, Map<String, Float>>> type2map = new HashMap<>();

        //  {
        //      破坏程度 : {烈度: 易损性}
        //  }
        //Map<String, Map<String, Float>> damageDegree2map = new HashMap<>();

        String province = getDivisionNameByCode("province", queryParams.getProvince());
        String city = getDivisionNameByCode("city", queryParams.getCity());
        String area = getDivisionNameByCode("district", queryParams.getArea());

        FxVulnerabilityProvinceQueryParams fxVulnerabilityProvinceQueryParams = new FxVulnerabilityProvinceQueryParams();
        fxVulnerabilityProvinceQueryParams.setProvince(province);
        fxVulnerabilityProvinceQueryParams.setCity(city);
        fxVulnerabilityProvinceQueryParams.setArea(area);
        List<FxVulnerabilityProvinceEntity> fxVulnerabilityProvinceEntities = fxVulnerabilityProvinceNativeRepository.listFxVulnerabilityProvinces(fxVulnerabilityProvinceQueryParams);

        FxVulnerabilityProvinceEntity fxVulnerabilityProvinceEntity = null;
        String district = "", damageDegree = "", structureType = "";
        Float vVI = 0.0f, vVII = 0.0f, vVIII = 0.0f, vIX = 0.0f, vX = 0.0f;
        for (int i = 0; i < fxVulnerabilityProvinceEntities.size(); i++) {
            fxVulnerabilityProvinceEntity = fxVulnerabilityProvinceEntities.get(i);

            province = fxVulnerabilityProvinceEntity.getProvince();
            city = fxVulnerabilityProvinceEntity.getCity();
            area = fxVulnerabilityProvinceEntity.getArea();

            structureType = fxVulnerabilityProvinceEntity.getStructureType();
            damageDegree = fxVulnerabilityProvinceEntity.getDamageDegree();

            vVI = fxVulnerabilityProvinceEntity.getVulnerabilityVI();
            vVII = fxVulnerabilityProvinceEntity.getVulnerabilityVII();
            vVIII = fxVulnerabilityProvinceEntity.getVulnerabilityVIII();
            vIX = fxVulnerabilityProvinceEntity.getVulnerabilityIX();
            vX = fxVulnerabilityProvinceEntity.getVulnerabilityX();

            district = province + "-" + city + "-" + area;
            if (!fxVulnerabilityProvince.containsKey(district)) {
                Map<String, Map<String, Map<String, Float>>> type2map = new HashMap<>();
                Map<String, Map<String, Float>> damageDegree2map = new HashMap<>();
                Map<String, Float> intensity2vulnerability = new HashMap<>();
                intensity2vulnerability.put("6", vVI);
                intensity2vulnerability.put("7", vVII);
                intensity2vulnerability.put("8", vVIII);
                intensity2vulnerability.put("9", vIX);
                intensity2vulnerability.put("10", vX);
                damageDegree2map.put(damageDegree, intensity2vulnerability);
                type2map.put(structureType, damageDegree2map);
                fxVulnerabilityProvince.put(district, type2map);
            } else {
                Map<String, Map<String, Map<String, Float>>> type2map = fxVulnerabilityProvince.get(district);
                if (!type2map.containsKey(structureType)) {
                    Map<String, Map<String, Float>> damageDegree2map = new HashMap<>();
                    Map<String, Float> intensity2vulnerability = new HashMap<>();
                    intensity2vulnerability.put("6", vVI);
                    intensity2vulnerability.put("7", vVII);
                    intensity2vulnerability.put("8", vVIII);
                    intensity2vulnerability.put("9", vIX);
                    intensity2vulnerability.put("10", vX);
                    damageDegree2map.put(damageDegree, intensity2vulnerability);
                    type2map.put(structureType, damageDegree2map);
                } else {
                    Map<String, Map<String, Float>> damageDegree2map = type2map.get(structureType);
                    if (!damageDegree2map.containsKey(damageDegree)) {
                        Map<String, Float> intensity2vulnerability = new HashMap<>();
                        intensity2vulnerability.put("6", vVI);
                        intensity2vulnerability.put("7", vVII);
                        intensity2vulnerability.put("8", vVIII);
                        intensity2vulnerability.put("9", vIX);
                        intensity2vulnerability.put("10", vX);
                        damageDegree2map.put(damageDegree, intensity2vulnerability);
                    } else {
                        System.out.println(district + ", structureType: " + structureType + ", damageDegree: " + damageDegree + ", 出现冗余数据!");
                    }
                }
            }
        }
        return fxVulnerabilityProvince;
    }
    @Autowired
    private FxDamagePercentNativeRepository fxDamagePercentNativeRepository;
    private Map<String, Map<String, Float>> damagePercent = new HashMap<>();
    private Map<String, Map<String, Float>> getDamagePercent(FxDamagePercentQueryParams queryParams) {
        //  {结构类型:
        //      { 破坏等级 : 破坏比例值}
        //  }
        String structureType = "", intact = "", slight = "", medium = "", serious = "", whole = "";
        FxDamagePercentEntity fxDamagePercentEntity = null;
        List<FxDamagePercentEntity> fxDamagePercents = this.fxDamagePercentNativeRepository.listFxDamagePercents(queryParams);
        for (int i = 0; i < fxDamagePercents.size(); i++) {
            fxDamagePercentEntity = fxDamagePercents.get(i);
            structureType = fxDamagePercentEntity.getStructureType();
            intact = fxDamagePercentEntity.getIntact(); intact = (intact != null ? intact : "0.0");
            slight = fxDamagePercentEntity.getSlight(); slight = (slight != null ? slight : "0.0");
            medium = fxDamagePercentEntity.getMedium(); medium = (medium != null ? medium : "0.0");
            serious = fxDamagePercentEntity.getSerious(); serious = (serious != null ? serious : "0.0");
            whole = fxDamagePercentEntity.getWhole(); whole = (whole != null ? whole : "0.0");

            Map<String, Float> code2value = new HashMap<>();
            code2value.put("0", Float.parseFloat(intact));
            code2value.put("1", Float.parseFloat(slight));
            code2value.put("2", Float.parseFloat(medium));
            code2value.put("3", Float.parseFloat(serious));
            code2value.put("4", Float.parseFloat(whole));
            damagePercent.put(structureType, code2value);
        }
        return damagePercent;
    }
    @Autowired
    private FxEconomicLossNativeRepository fxEconomicLossNativeRepository;
    private Map<String, Map<String, Float>> resetUnitPrice = new HashMap<>();
    private Map<String, Map<String, Float>> getResetUnitPrice(FxEconomicLossQueryParams queryParams){
        //  {省-市-县:
        //      { 结构类型 : 重置单价}
        //  }
        String province = "", city = "", area = "", structureType = "", district = "";
        BigDecimal price = null;
        FxEconomicLossEntity fxEconomicLossEntity = null;
        List<FxEconomicLossEntity> fxDamagePercents = this.fxEconomicLossNativeRepository.listFxEconomicLosss(queryParams);
        for (int i = 0; i < fxDamagePercents.size(); i++) {
            fxEconomicLossEntity = fxDamagePercents.get(i);
            province = fxEconomicLossEntity.getProvince();
            city = fxEconomicLossEntity.getCity();
            area = fxEconomicLossEntity.getArea();
            structureType = fxEconomicLossEntity.getStructureType();
            price = fxEconomicLossEntity.getPrice();

            district = province + "-" + city + "-" + area;
            if (resetUnitPrice.containsKey(district)) {
                Map<String, Float> type2value = resetUnitPrice.get(district);
                type2value.put(structureType, price.floatValue());
            } else {
                Map<String, Float> type2value = new HashMap<>();
                type2value.put(structureType, price.floatValue());
                resetUnitPrice.put(district, type2value);
            }
        }
        return resetUnitPrice;
    }
    @Autowired
    private FxVulnerabilityDangerNativeRepository fxVulnerabilityDangerNativeRepository;
    private Map<String, Map<String, Float>> vulnerabilityDanger = new HashMap<>();
    private Map<String, Map<String, Float>> getVulnerabilityDanger(FxVulnerabilityDangerQueryParams queryParams){
        //  {省-市-县:
        //      { 地震动强度 : 概率值}
        //  }
        String province = "", city = "", area = "", district = "";
        Float viProbability = 0.0f, viiProbability = 0.0f, viiiProbability = 0.0f, ixProbability = 0.0f, xProbability = 0.0f;
        BigDecimal price = null;
        FxVulnerabilityDangerEntity fxEconomicLossEntity = null;
        List<FxVulnerabilityDangerEntity> fxDamagePercents = this.fxVulnerabilityDangerNativeRepository.listFxVulnerabilityDangers(queryParams);
        for (int i = 0; i < fxDamagePercents.size(); i++) {
            fxEconomicLossEntity = fxDamagePercents.get(i);

            province = fxEconomicLossEntity.getProvince();
            city = fxEconomicLossEntity.getCity();
            area = fxEconomicLossEntity.getArea();

            viProbability = fxEconomicLossEntity.getViEarthquakeIntensity();
            viiProbability = fxEconomicLossEntity.getViiEarthquakeIntensity();
            viiiProbability = fxEconomicLossEntity.getViiiEarthquakeIntensity();
            ixProbability = fxEconomicLossEntity.getIxEarthquakeIntensity();
            xProbability = fxEconomicLossEntity.getXEarthquakeIntensity();

            Map<String, Float> intensity2Probability = new HashMap<>();
            intensity2Probability.put("6", viProbability);
            intensity2Probability.put("7", viiProbability);
            intensity2Probability.put("8", viiiProbability);
            intensity2Probability.put("9", ixProbability);
            intensity2Probability.put("10", xProbability);

            district = province + "-" + city + "-" + area;
            vulnerabilityDanger.put(district, intensity2Probability);
        }
        return vulnerabilityDanger;
    }

    private Map<String, Map<String, Map<String, Float>>> probabilityVulnerability = new HashMap<>();
    private Map<String, Map<String, Map<String, Float>>> getProbabilityVulnerability(String district){
        //
        // {省-市-区县:
        //  {房屋结构类型: { 破坏程度 : 易损性 }
        //  }
        Map<String, Float> intensity2Probability = vulnerabilityDanger.get(district);
        Map<String, Map<String, Float>> structType2map = new HashMap<>();
        Map<String, Map<String, Map<String, Float>>> typeToMap = fxVulnerabilityProvince.get(district);;
        for(Map.Entry<String, Map<String, Map<String, Float>>> entryJ : typeToMap.entrySet()) {
            String structType = entryJ.getKey();
            Map<String, Float> damage2vulnerability = new HashMap<>();
            Map<String, Map<String, Float>> damage2map = entryJ.getValue();
            for(Map.Entry<String, Map<String, Float>> entryK : damage2map.entrySet()) {
                String damage = entryK.getKey();
                Float pVulnerability = 0.0f;
                Map<String, Float> intensity2vulnerability = entryK.getValue();
                for(Map.Entry<String, Float> entryL : intensity2vulnerability.entrySet()) {
                    String intensity = entryL.getKey();
                    Float vulnerability = entryL.getValue();
                    Float probability = intensity2Probability.get(intensity);
                    pVulnerability += (probability != null ? probability : 0.0f) * vulnerability;
                }
                damage2vulnerability.put(damage, pVulnerability);
            }
            structType2map.put(structType, damage2vulnerability);
        }
        probabilityVulnerability.put(district, structType2map);

        return probabilityVulnerability;
    }


    private Map<String, Map<String, String>> divisionCodeToName = new HashMap<>();
    private String getDivisionNameByCode (String level, String code) {
        if (divisionCodeToName.size() == 0) divisionCodeToName = initDivisionNameByCode();
        return divisionCodeToName.get(level).get(code);
    }
    private Map<String, Map<String, String>> initDivisionNameByCode () {
        Map<String, Map<String, String>> divisionCodeToName = new HashMap<>();

        Map<String, String> provinceCodeToName = new HashMap<>();
        Map<String, String> cityCodeToName = new HashMap<>();
        Map<String, String> districtCodeToName = new HashMap<>();

        String divisionId = "", provinceCode = "", provinceName = "", cityCode = "", cityName = "", districtCode = "", districtName = "";
        DivisionEntity divisionEntity = null;
        List<DivisionEntity> divisionEntities_1 = PlatformAPI.getDivisionAPI().getSubDivisions("root");
        for (int i = 0; i < divisionEntities_1.size(); i++) {
            divisionEntity = divisionEntities_1.get(i);
            provinceCode = divisionEntity.getDivisionCode();
            provinceName = divisionEntity.getDivisionName();
            provinceCodeToName.put(provinceCode, provinceName);

            divisionId = divisionEntity.getDivisionId();
            List<DivisionEntity> divisionEntities_2 = PlatformAPI.getDivisionAPI().getSubDivisions(divisionId);
            for (int j = 0; j < divisionEntities_2.size(); j++) {
                divisionEntity = divisionEntities_2.get(j);
                cityCode = divisionEntity.getDivisionCode();
                cityName = divisionEntity.getDivisionName();
                cityCodeToName.put(cityCode, cityName);

                divisionId = divisionEntity.getDivisionId();
                List<DivisionEntity> divisionEntities_3 = PlatformAPI.getDivisionAPI().getSubDivisions(divisionId);
                for (int k = 0; k < divisionEntities_3.size(); k++) {
                    divisionEntity = divisionEntities_3.get(k);
                    districtCode = divisionEntity.getDivisionCode();
                    districtName = divisionEntity.getDivisionName();
                    districtCodeToName.put(districtCode, districtName);
                }
            }
        }
        divisionCodeToName.put("province", provinceCodeToName);
        divisionCodeToName.put("city", cityCodeToName);
        divisionCodeToName.put("district", districtCodeToName);
        return divisionCodeToName;
    }
}
